bitkeeper revision 1.825.4.3 (40642185aZwwgLwBAies8HKAne40aw)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 26 Mar 2004 12:26:45 +0000 (12:26 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 26 Mar 2004 12:26:45 +0000 (12:26 +0000)
Many files:
  Adding physirq support to new Xen upcall interface.
.del-physirq.c~e02f2ea038df07fa:
  Delete: xenolinux-2.4.25-sparse/arch/xen/kernel/physirq.c

.rootkeys
xen/common/event_channel.c
xen/common/physdev.c
xen/include/hypervisor-ifs/dom0_ops.h
xen/include/hypervisor-ifs/event_channel.h
xen/include/hypervisor-ifs/physdev.h
xenolinux-2.4.25-sparse/arch/xen/kernel/Makefile
xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c
xenolinux-2.4.25-sparse/arch/xen/kernel/physirq.c [deleted file]
xenolinux-2.4.25-sparse/include/asm-xen/irq.h

index 2caa01cd046d9459c2b5f00bb547852e1e1001e7..03b625759ba9cd266601123bb0ad38eba4f99844 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 4051db8dJYX86ZCLA-WfTW2dAyrehw xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.h
 4051db91BenvDZEMZxQCGkQyJYoG5w xenolinux-2.4.25-sparse/arch/xen/kernel/pci-irq.c
 4051db95N9N99FjsRwi49YKUNHWI8A xenolinux-2.4.25-sparse/arch/xen/kernel/pci-pc.c
-4051db99fbdTHgCpjywPCp7vjLCe7Q xenolinux-2.4.25-sparse/arch/xen/kernel/physirq.c
 3e5a4e65IGt3WwQDNiL4h-gYWgNTWQ xenolinux-2.4.25-sparse/arch/xen/kernel/process.c
 3e5a4e66tR-qJMLj3MppcKqmvuI2XQ xenolinux-2.4.25-sparse/arch/xen/kernel/setup.c
 3e5a4e66fWSTagLGU2P8BGFGRjhDiw xenolinux-2.4.25-sparse/arch/xen/kernel/signal.c
index f5e48f366e519ce7aab2bddc36fc81ed410c6869..d0c0f5bba0042ae5e916d5aadb60fa07fea84cfd 100644 (file)
@@ -146,7 +146,7 @@ static long evtchn_bind_virq(evtchn_bind_virq_t *bind)
     int virq = bind->virq;
     int port;
 
-    if ( virq >= NR_VIRQS )
+    if ( virq >= ARRAY_SIZE(p->virq_to_evtchn) )
         return -EINVAL;
 
     spin_lock(&p->event_channel_lock);
@@ -177,6 +177,37 @@ static long evtchn_bind_virq(evtchn_bind_virq_t *bind)
 }
 
 
+static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind)
+{
+    struct task_struct *p = current;
+    int pirq = bind->pirq;
+    int port;
+
+    if ( pirq >= ARRAY_SIZE(p->pirq_to_evtchn) )
+        return -EINVAL;
+
+    spin_lock(&p->event_channel_lock);
+
+    if ( ((port = p->pirq_to_evtchn[pirq]) != 0) ||
+         ((port = get_free_port(p)) < 0) )
+        goto out;
+
+    p->event_channel[port].state  = ECS_PIRQ;
+    p->event_channel[port].u.pirq = pirq;
+
+    p->pirq_to_evtchn[pirq] = port;
+
+ out:
+    spin_unlock(&p->event_channel_lock);
+
+    if ( port < 0 )
+        return port;
+
+    bind->port = port;
+    return 0;
+}
+
+
 static long __evtchn_close(struct task_struct *p1, int port1)
 {
     struct task_struct *p2 = NULL;
@@ -396,13 +427,19 @@ long do_event_channel_op(evtchn_op_t *uop)
     {
     case EVTCHNOP_bind_interdomain:
         rc = evtchn_bind_interdomain(&op.u.bind_interdomain);
-        if ( copy_to_user(uop, &op, sizeof(op)) != 0 )
+        if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
             rc = -EFAULT; /* Cleaning up here would be a mess! */
         break;
 
     case EVTCHNOP_bind_virq:
         rc = evtchn_bind_virq(&op.u.bind_virq);
-        if ( copy_to_user(uop, &op, sizeof(op)) != 0 )
+        if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
+            rc = -EFAULT; /* Cleaning up here would be a mess! */
+        break;
+
+    case EVTCHNOP_bind_pirq:
+        rc = evtchn_bind_pirq(&op.u.bind_pirq);
+        if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
             rc = -EFAULT; /* Cleaning up here would be a mess! */
         break;
 
@@ -416,7 +453,7 @@ long do_event_channel_op(evtchn_op_t *uop)
 
     case EVTCHNOP_status:
         rc = evtchn_status(&op.u.status);
-        if ( copy_to_user(uop, &op, sizeof(op)) != 0 )
+        if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
             rc = -EFAULT;
         break;
 
index da22f88cfe6514b5491c1eedafd38c3e529b665e..08da1b5206895b62968872c537d46d2171215050 100644 (file)
@@ -601,7 +601,7 @@ static void end_virt_irq (unsigned int i)
  * - shared interrupts are not allowed for now
  * - we change the hw_irq handler to something else
  */
-static long pci_request_irq(int irq)
+static long pirq_request(int irq)
 {
     int err;
     phys_dev_t *pdev = NULL, *t;
@@ -685,7 +685,7 @@ static long pci_request_irq(int irq)
     return 0;
 }
 
-static long pci_free_irq(int irq)
+long pirq_free(int irq)
 {
     phys_dev_t *pdev;
 
@@ -719,55 +719,12 @@ static long pci_free_irq(int irq)
     return 0;
 }
 
-static long pci_enable_irq(int irq)
+static long pci_unmask_irq(void)
 {
-    /* XXX not sure we need this */
-    /* guest can enable phys_irq event for now */
-    return 0;
-}
-
-static long pci_disable_irq(int irq)
-{
-    /* XXX not sure we need this */
-    /* guest can disable phys_irq event for now */
-    return 0;
-}
-
-static long pci_finished_irq(int irq)
-{
-    phys_dev_t *pdev;
-    
-    if ( !(pdev = irqs[irq]) )
-    {
-        printk("finished_irq called for unregistered irq %d\n", irq);
-        return -EINVAL;
-    }
-   
-    if ( pdev->owner != current )
-    {
-        printk("finished_irq called dom not owning irq %d\n", irq);
-        return -EPERM;
-    }
-
-    if ( !test_bit(ST_IRQ_DELIVERED, &pdev->state) )
-    {
-        printk("finished_irq called for undelivered irq %d\n", irq);
-        return -EINVAL;
-    }
-
-#if 0 /* XXX KAF: do we need this? */
-    if ( test_bit(irq, &current->shared_info->physirq_pend) )
-    {
-        printk("finished_irq called for un-acknowleged irq %d\n", irq);        
-        return -EINVAL;
-    }
-#endif
-
+#if 0
     clear_bit(ST_IRQ_DELIVERED, &pdev->state);
-
-    /* call original end handler */
     pdev->orig_handler->end(irq);
-
+#endif
     return 0;
 }
 
@@ -786,43 +743,27 @@ long do_physdev_op(physdev_op_t *uop)
     switch ( op.cmd )
     {
     case PHYSDEVOP_CFGREG_READ:
-        ret = pci_cfgreg_read (op.u.cfg_read.seg, op.u.cfg_read.bus,
-                               op.u.cfg_read.dev, op.u.cfg_read.func,
-                               op.u.cfg_read.reg, op.u.cfg_read.len,
-                               &op.u.cfg_read.value);
+        ret = pci_cfgreg_read(op.u.cfg_read.seg, op.u.cfg_read.bus,
+                              op.u.cfg_read.dev, op.u.cfg_read.func,
+                              op.u.cfg_read.reg, op.u.cfg_read.len,
+                              &op.u.cfg_read.value);
         break;
 
     case PHYSDEVOP_CFGREG_WRITE:
-        ret = pci_cfgreg_write (op.u.cfg_write.seg, op.u.cfg_write.bus,
-                                op.u.cfg_write.dev, op.u.cfg_write.func,
-                                op.u.cfg_write.reg, op.u.cfg_write.len,
-                                op.u.cfg_write.value);
+        ret = pci_cfgreg_write(op.u.cfg_write.seg, op.u.cfg_write.bus,
+                               op.u.cfg_write.dev, op.u.cfg_write.func,
+                               op.u.cfg_write.reg, op.u.cfg_write.len,
+                               op.u.cfg_write.value);
         break;
 
     case PHYSDEVOP_FIND_IRQ:
-        ret = pci_find_irq (op.u.find_irq.seg, op.u.find_irq.bus,
-                            op.u.find_irq.dev, op.u.find_irq.func,
-                            &op.u.find_irq.irq);
-        break;
-
-    case PHYSDEVOP_REQUEST_IRQ:
-        ret = pci_request_irq (op.u.request_irq.irq);
-        break;
-
-    case PHYSDEVOP_FREE_IRQ:
-        ret = pci_free_irq (op.u.free_irq.irq);
-        break;
-
-    case PHYSDEVOP_ENABLE_IRQ:
-        ret = pci_enable_irq (op.u.enable_irq.irq);
-        break;
-
-    case PHYSDEVOP_DISABLE_IRQ:
-        ret = pci_disable_irq (op.u.disable_irq.irq);
+        ret = pci_find_irq(op.u.find_irq.seg, op.u.find_irq.bus,
+                           op.u.find_irq.dev, op.u.find_irq.func,
+                           &op.u.find_irq.irq);
         break;
 
-    case PHYSDEVOP_FINISHED_IRQ:
-        ret = pci_finished_irq (op.u.finished_irq.irq);
+    case PHYSDEVOP_UNMASK_IRQ:
+        ret = pci_unmask_irq();
         break;
 
     default:
index 8574f02531ff713828d080f797142428cae0621e..ce748d5d3188d40303a70143d3e0d48ee95c7dfa 100644 (file)
@@ -18,7 +18,7 @@
  * This makes sure that old versions of dom0 tools will stop working in a
  * well-defined way (rather than crashing the machine, for instance).
  */
-#define DOM0_INTERFACE_VERSION   0xAAAA0009
+#define DOM0_INTERFACE_VERSION   0xAAAA000A
 
 #define MAX_CMD_LEN       256
 #define MAX_DOMAIN_NAME    16
index 6fae72cc383586bc9d87c0be74bdeb76aee7dd57..fdc4eaeb1bc211c17a1bc80439a91ef081f8de13 100644 (file)
@@ -30,7 +30,7 @@ typedef struct evtchn_bind_interdomain
  * NOTES:
  *  1. A virtual IRQ may be bound to at most one event channel per domain.
  */
-#define EVTCHNOP_bind_virq    1
+#define EVTCHNOP_bind_virq        1
 typedef struct evtchn_bind_virq
 {
     /* IN parameters. */
@@ -39,6 +39,21 @@ typedef struct evtchn_bind_virq
     int port;
 } evtchn_bind_virq_t;
 
+/*
+ * EVTCHNOP_bind_pirq: Bind a local event channel to IRQ <irq>.
+ * NOTES:
+ *  1. A physical IRQ may be bound to at most one event channel per domain.
+ *  2. Only a sufficiently-privileged domain may bind to a physical IRQ.
+ */
+#define EVTCHNOP_bind_pirq        2
+typedef struct evtchn_bind_pirq
+{
+    /* IN parameters. */
+    int pirq;
+    /* OUT parameters. */
+    int port;
+} evtchn_bind_pirq_t;
+
 /*
  * EVTCHNOP_close: Close the communication channel which has an endpoint at
  * <dom, port>.
@@ -47,7 +62,7 @@ typedef struct evtchn_bind_virq
  *  2. Only a sufficiently-privileged domain may close an event channel
  *     for which <dom> is not DOMID_SELF.
  */
-#define EVTCHNOP_close            2
+#define EVTCHNOP_close            3
 typedef struct evtchn_close
 {
     /* IN parameters. */
@@ -60,7 +75,7 @@ typedef struct evtchn_close
  * EVTCHNOP_send: Send an event to the remote end of the channel whose local
  * endpoint is <DOMID_SELF, local_port>.
  */
-#define EVTCHNOP_send             3
+#define EVTCHNOP_send             4
 typedef struct evtchn_send
 {
     /* IN parameters. */
@@ -76,7 +91,7 @@ typedef struct evtchn_send
  *  2. Only a sufficiently-privileged domain may obtain the status of an event
  *     channel for which <dom> is not DOMID_SELF.
  */
-#define EVTCHNOP_status           4
+#define EVTCHNOP_status           5
 typedef struct evtchn_status
 {
     /* IN parameters */
@@ -86,8 +101,8 @@ typedef struct evtchn_status
 #define EVTCHNSTAT_closed       0  /* Chennel is not in use.                 */
 #define EVTCHNSTAT_unbound      1  /* Channel is not bound to a source.      */
 #define EVTCHNSTAT_interdomain  2  /* Channel is connected to remote domain. */
-#define EVTCHNSTAT_pirq     3      /* Channel is bound to a phys IRQ line.   */
-#define EVTCHNSTAT_virq     4      /* Channel is bound to a virtual IRQ line */
+#define EVTCHNSTAT_pirq         3  /* Channel is bound to a phys IRQ line.   */
+#define EVTCHNSTAT_virq         4  /* Channel is bound to a virtual IRQ line */
     int     status;
     union {
         int __none;    /* EVTCHNSTAT_closed, EVTCHNSTAT_unbound */
@@ -106,6 +121,7 @@ typedef struct evtchn_op
     union {
         evtchn_bind_interdomain_t bind_interdomain;
         evtchn_bind_virq_t        bind_virq;
+        evtchn_bind_pirq_t        bind_pirq;
         evtchn_close_t            close;
         evtchn_send_t             send;
         evtchn_status_t           status;
index 925023056c3cc86e6ace13ee6efcee5ef3cc398a..383bb13097bcb792702e068521e651cc8bde9435 100644 (file)
 #define PHYSDEVOP_CFGREG_READ   0
 #define PHYSDEVOP_CFGREG_WRITE  1
 #define PHYSDEVOP_FIND_IRQ      2
-#define PHYSDEVOP_REQUEST_IRQ   3
-#define PHYSDEVOP_FREE_IRQ      4
-#define PHYSDEVOP_ENABLE_IRQ    5
-#define PHYSDEVOP_DISABLE_IRQ   6
-#define PHYSDEVOP_FINISHED_IRQ  7
+#define PHYSDEVOP_UNMASK_IRQ    3
 
 /* read pci config */
 typedef struct physdevop_cfgreg_read_st
@@ -32,8 +28,8 @@ typedef struct physdevop_cfgreg_read_st
     int bus;        /* IN */
     int dev;        /* IN */
     int func;       /* IN */
-    int reg;        /* IN  */
-    int len;        /* IN  */
+    int reg;        /* IN */
+    int len;        /* IN */
     u32 value;      /* OUT */
 } physdevop_cfgreg_read_t;
 
@@ -59,36 +55,6 @@ typedef struct physdevop_find_irq_st
     u32 irq;      /* OUT */
 } physdevop_find_irq_t;
 
-/* request physical IRQ to be routed to guest */
-typedef struct physdevop_request_irq_st
-{
-    u32 irq;      /* IN */
-} physdevop_request_irq_t;
-
-/* stop routing physical interrupts to guest */
-typedef struct physdevop_free_irq_st
-{
-    u32 irq;      /* IN */
-} physdevop_free_irq_t;
-
-/* enable IRQ for the caller  */
-typedef struct physdevop_enable_irq_st
-{
-    u32 irq;      /* IN */
-} physdevop_enable_irq_t;
-
-/* disable interrupts */
-typedef struct physdevop_disable_irq_st
-{
-    u32 irq;      /* IN */
-} physdevop_disable_irq_t;
-
-typedef struct physdevop_finished_irq_st
-{
-    u32 irq;      /* IN */
-} physdevop_finished_irq_t;
-
-
 typedef struct _physdev_op_st 
 {
     unsigned long cmd;
@@ -99,11 +65,6 @@ typedef struct _physdev_op_st
         physdevop_cfgreg_read_t  cfg_read;
         physdevop_cfgreg_write_t cfg_write;
         physdevop_find_irq_t     find_irq;
-        physdevop_request_irq_t  request_irq;
-        physdevop_free_irq_t     free_irq;
-        physdevop_enable_irq_t   enable_irq;
-        physdevop_disable_irq_t  disable_irq;
-        physdevop_finished_irq_t finished_irq;
     } u;
 } physdev_op_t;
 
index 9f86b6d297cb0b2c4bf23e624759f832859f0abc..5abf0a0d6244ab0c6fec9cba096ce55ac6c64bfd 100644 (file)
@@ -10,7 +10,7 @@ export-objs     := i386_ksyms.o
 
 obj-y  := process.o semaphore.o signal.o entry.o traps.o irq.o  \
                ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o \
-               i386_ksyms.o i387.o evtchn.o physirq.o pci-dma.o
+               i386_ksyms.o i387.o evtchn.o pci-dma.o
 
 ifdef CONFIG_PCI
 obj-y  += pci-i386.o pci-pc.o pci-irq.o
index 266867fc74bdadeb3d2bb173412f969272ea69d9..4eb83c4b4cf5493c7eeee5ee6fc72435677d8b9c 100644 (file)
 #include <asm/synch_bitops.h>
 #include <asm/hypervisor.h>
 #include <asm/hypervisor-ifs/event_channel.h>
-
-/* Dynamic IRQ <-> event-channel mappings. */
-static int evtchn_to_dynirq[1024];
-static int dynirq_to_evtchn[NR_IRQS];
-
-/* Dynamic IRQ <-> VIRQ mapping. */
-static int virq_to_dynirq[NR_VIRQS];
+#include <asm/hypervisor-ifs/physdev.h>
 
 /*
- * Reference counts for bindings to dynamic IRQs.
- * NB. This array is referenced with respect to DYNIRQ_BASE!
+ * This lock protects updates to the following mapping and reference-count
+ * arrays. The lock does not need to be acquired to read the mapping tables.
  */
-static int dynirq_bindcount[NR_DYNIRQS];
-static spinlock_t dynirq_lock;
+static spinlock_t irq_mapping_update_lock;
+
+/* IRQ <-> event-channel mappings. */
+static int evtchn_to_irq[NR_EVENT_CHANNELS];
+static int irq_to_evtchn[NR_IRQS];
+
+/* IRQ <-> VIRQ mapping. */
+static int virq_to_irq[NR_VIRQS];
+
+/* Reference counts for bindings to IRQs. */
+static int irq_bindcount[NR_IRQS];
 
 /* Upcall to generic IRQ layer. */
 extern asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs);
@@ -39,7 +42,7 @@ static void evtchn_handle_normal(shared_info_t *s, struct pt_regs *regs)
 {
     unsigned long l1, l2;
     unsigned int  l1i, l2i, port;
-    int           dynirq;
+    int           irq;
 
     l1 = xchg(&s->evtchn_pending_sel, 0);
     while ( (l1i = ffs(l1)) != 0 )
@@ -54,8 +57,8 @@ static void evtchn_handle_normal(shared_info_t *s, struct pt_regs *regs)
             l2 &= ~(1 << l2i);
             
             port = (l1i << 5) + l2i;
-            if ( (dynirq = evtchn_to_dynirq[port]) != -1 )
-                do_IRQ(dynirq + DYNIRQ_BASE, regs);
+            if ( (irq = evtchn_to_irq[port]) != -1 )
+                do_IRQ(irq, regs);
             else
                 evtchn_device_upcall(port, 0);
         }
@@ -66,7 +69,7 @@ static void evtchn_handle_exceptions(shared_info_t *s, struct pt_regs *regs)
 {
     unsigned long l1, l2;
     unsigned int  l1i, l2i, port;
-    int           dynirq;
+    int           irq;
 
     l1 = xchg(&s->evtchn_exception_sel, 0);
     while ( (l1i = ffs(l1)) != 0 )
@@ -81,10 +84,9 @@ static void evtchn_handle_exceptions(shared_info_t *s, struct pt_regs *regs)
             l2 &= ~(1 << l2i);
             
             port = (l1i << 5) + l2i;
-            if ( (dynirq = evtchn_to_dynirq[port]) != -1 )
+            if ( (irq = evtchn_to_irq[port]) != -1 )
             {
-                printk(KERN_ALERT "Error on IRQ line %d!\n", 
-                       dynirq + DYNIRQ_BASE);
+                printk(KERN_ALERT "Error on IRQ line %d!\n", irq);
                 synch_clear_bit(port, &s->evtchn_exception[0]);
             }
             else
@@ -112,28 +114,28 @@ void evtchn_do_upcall(struct pt_regs *regs)
 }
 
 
-static int find_unbound_dynirq(void)
+static int find_unbound_irq(void)
 {
-    int i;
+    int irq;
 
-    for ( i = 0; i < NR_DYNIRQS; i++ )
-        if ( dynirq_bindcount[i] == 0 )
+    for ( irq = 0; irq < NR_IRQS; irq++ )
+        if ( irq_bindcount[irq] == 0 )
             break;
 
-    if ( i == NR_DYNIRQS )
+    if ( irq == NR_IRQS )
         BUG();
 
-    return i;
+    return irq;
 }
 
 int bind_virq_to_irq(int virq)
 {
     evtchn_op_t op;
-    int evtchn, dynirq;
+    int evtchn, irq;
 
-    spin_lock(&dynirq_lock);
+    spin_lock(&irq_mapping_update_lock);
 
-    if ( (dynirq = virq_to_dynirq[virq]) == -1 )
+    if ( (irq = virq_to_irq[virq]) == -1 )
     {
         op.cmd              = EVTCHNOP_bind_virq;
         op.u.bind_virq.virq = virq;
@@ -141,29 +143,29 @@ int bind_virq_to_irq(int virq)
             BUG();
         evtchn = op.u.bind_virq.port;
 
-        dynirq = find_unbound_dynirq();
-        evtchn_to_dynirq[evtchn] = dynirq;
-        dynirq_to_evtchn[dynirq] = evtchn;
+        irq = find_unbound_irq();
+        evtchn_to_irq[evtchn] = irq;
+        irq_to_evtchn[irq]    = evtchn;
 
-        virq_to_dynirq[virq] = dynirq;
+        virq_to_irq[virq] = irq;
     }
 
-    dynirq_bindcount[dynirq]++;
+    irq_bindcount[irq]++;
 
-    spin_unlock(&dynirq_lock);
+    spin_unlock(&irq_mapping_update_lock);
     
-    return dynirq + DYNIRQ_BASE;
+    return irq;
 }
 
 void unbind_virq_from_irq(int virq)
 {
     evtchn_op_t op;
-    int dynirq = virq_to_dynirq[virq];
-    int evtchn = dynirq_to_evtchn[dynirq];
+    int irq    = virq_to_irq[virq];
+    int evtchn = irq_to_evtchn[irq];
 
-    spin_lock(&dynirq_lock);
+    spin_lock(&irq_mapping_update_lock);
 
-    if ( --dynirq_bindcount[dynirq] == 0 )
+    if ( --irq_bindcount[irq] == 0 )
     {
         op.cmd          = EVTCHNOP_close;
         op.u.close.dom  = DOMID_SELF;
@@ -171,47 +173,47 @@ void unbind_virq_from_irq(int virq)
         if ( HYPERVISOR_event_channel_op(&op) != 0 )
             BUG();
 
-        evtchn_to_dynirq[evtchn] = -1;
-        dynirq_to_evtchn[dynirq] = -1;
-        virq_to_dynirq[virq]     = -1;
+        evtchn_to_irq[evtchn] = -1;
+        irq_to_evtchn[irq]    = -1;
+        virq_to_irq[virq]     = -1;
     }
 
-    spin_unlock(&dynirq_lock);
+    spin_unlock(&irq_mapping_update_lock);
 }
 
 int bind_evtchn_to_irq(int evtchn)
 {
-    int dynirq;
+    int irq;
 
-    spin_lock(&dynirq_lock);
+    spin_lock(&irq_mapping_update_lock);
 
-    if ( (dynirq = evtchn_to_dynirq[evtchn]) == -1 )
+    if ( (irq = evtchn_to_irq[evtchn]) == -1 )
     {
-        dynirq = find_unbound_dynirq();
-        evtchn_to_dynirq[evtchn] = dynirq;
-        dynirq_to_evtchn[dynirq] = evtchn;
+        irq = find_unbound_irq();
+        evtchn_to_irq[evtchn] = irq;
+        irq_to_evtchn[irq]    = evtchn;
     }
 
-    dynirq_bindcount[dynirq]++;
+    irq_bindcount[irq]++;
 
-    spin_unlock(&dynirq_lock);
+    spin_unlock(&irq_mapping_update_lock);
     
-    return dynirq + DYNIRQ_BASE;
+    return irq;
 }
 
 void unbind_evtchn_from_irq(int evtchn)
 {
-    int dynirq = evtchn_to_dynirq[evtchn];
+    int irq = evtchn_to_irq[evtchn];
 
-    spin_lock(&dynirq_lock);
+    spin_lock(&irq_mapping_update_lock);
 
-    if ( --dynirq_bindcount[dynirq] == 0 )
+    if ( --irq_bindcount[irq] == 0 )
     {
-        evtchn_to_dynirq[evtchn] = -1;
-        dynirq_to_evtchn[dynirq] = -1;
+        evtchn_to_irq[evtchn] = -1;
+        irq_to_evtchn[irq]    = -1;
     }
 
-    spin_unlock(&dynirq_lock);
+    spin_unlock(&irq_mapping_update_lock);
 }
 
 
@@ -221,41 +223,35 @@ void unbind_evtchn_from_irq(int evtchn)
 
 static unsigned int startup_dynirq(unsigned int irq)
 {
-    int dynirq = irq - DYNIRQ_BASE;
-    unmask_evtchn(dynirq_to_evtchn[dynirq]);
+    unmask_evtchn(irq_to_evtchn[irq]);
     return 0;
 }
 
 static void shutdown_dynirq(unsigned int irq)
 {
-    int dynirq = irq - DYNIRQ_BASE;
-    mask_evtchn(dynirq_to_evtchn[dynirq]);
+    mask_evtchn(irq_to_evtchn[irq]);
 }
 
 static void enable_dynirq(unsigned int irq)
 {
-    int dynirq = irq - DYNIRQ_BASE;
-    unmask_evtchn(dynirq_to_evtchn[dynirq]);
+    unmask_evtchn(irq_to_evtchn[irq]);
 }
 
 static void disable_dynirq(unsigned int irq)
 {
-    int dynirq = irq - DYNIRQ_BASE;
-    mask_evtchn(dynirq_to_evtchn[dynirq]);
+    mask_evtchn(irq_to_evtchn[irq]);
 }
 
 static void ack_dynirq(unsigned int irq)
 {
-    int dynirq = irq - DYNIRQ_BASE;
-    mask_evtchn(dynirq_to_evtchn[dynirq]);
-    clear_evtchn(dynirq_to_evtchn[dynirq]);
+    mask_evtchn(irq_to_evtchn[irq]);
+    clear_evtchn(irq_to_evtchn[irq]);
 }
 
 static void end_dynirq(unsigned int irq)
 {
-    int dynirq = irq - DYNIRQ_BASE;
     if ( !(irq_desc[irq].status & IRQ_DISABLED) )
-        unmask_evtchn(dynirq_to_evtchn[dynirq]);
+        unmask_evtchn(irq_to_evtchn[irq]);
 }
 
 static struct hw_interrupt_type dynirq_type = {
@@ -269,6 +265,87 @@ static struct hw_interrupt_type dynirq_type = {
     NULL
 };
 
+static inline void pirq_unmask_notify(int pirq)
+{
+    physdev_op_t op;
+    op.cmd = PHYSDEVOP_UNMASK_IRQ;
+    (void)HYPERVISOR_physdev_op(&op);
+}
+
+static unsigned int startup_pirq(unsigned int irq)
+{
+    evtchn_op_t op;
+    int evtchn;
+
+    op.cmd              = EVTCHNOP_bind_pirq;
+    op.u.bind_pirq.pirq = irq;
+    if ( HYPERVISOR_event_channel_op(&op) != 0 )
+        BUG();
+    evtchn = op.u.bind_virq.port;
+
+    evtchn_to_irq[evtchn] = irq;
+    irq_to_evtchn[irq]    = evtchn;
+
+    unmask_evtchn(evtchn);
+    pirq_unmask_notify(irq_to_pirq(irq));
+
+    return 0;
+}
+
+static void shutdown_pirq(unsigned int irq)
+{
+    evtchn_op_t op;
+    int evtchn = irq_to_evtchn[irq];
+
+    mask_evtchn(evtchn);
+
+    op.cmd          = EVTCHNOP_close;
+    op.u.close.dom  = DOMID_SELF;
+    op.u.close.port = evtchn;
+    if ( HYPERVISOR_event_channel_op(&op) != 0 )
+        BUG();
+
+    evtchn_to_irq[evtchn] = -1;
+    irq_to_evtchn[irq]    = -1;
+}
+
+static void enable_pirq(unsigned int irq)
+{
+    unmask_evtchn(irq_to_evtchn[irq]);
+    pirq_unmask_notify(irq_to_pirq(irq));
+}
+
+static void disable_pirq(unsigned int irq)
+{
+    mask_evtchn(irq_to_evtchn[irq]);
+}
+
+static void ack_pirq(unsigned int irq)
+{
+    mask_evtchn(irq_to_evtchn[irq]);
+    clear_evtchn(irq_to_evtchn[irq]);
+}
+
+static void end_pirq(unsigned int irq)
+{
+    if ( !(irq_desc[irq].status & IRQ_DISABLED) )
+    {
+        unmask_evtchn(irq_to_evtchn[irq]);
+        pirq_unmask_notify(irq_to_pirq(irq));
+    }
+}
+
+static struct hw_interrupt_type pirq_type = {
+    "Phys-irq",
+    startup_pirq,
+    shutdown_pirq,
+    enable_pirq,
+    disable_pirq,
+    ack_pirq,
+    end_pirq,
+    NULL
+};
+
 static void error_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
     printk(KERN_ALERT "unexpected VIRQ_ERROR trap to vector %d\n", irq);
@@ -287,32 +364,41 @@ void __init init_IRQ(void)
 {
     int i;
 
+    spin_lock_init(&irq_mapping_update_lock);
+
+    /* No VIRQ -> IRQ mappings. */
     for ( i = 0; i < NR_VIRQS; i++ )
-        virq_to_dynirq[i] = -1;
+        virq_to_irq[i] = -1;
 
-    for ( i = 0; i < 1024; i++ )
-        evtchn_to_dynirq[i] = -1;
+    /* No event-channel -> IRQ mappings. */
+    for ( i = 0; i < NR_EVENT_CHANNELS; i++ )
+        evtchn_to_irq[i] = -1;
+
+    /* No IRQ -> event-channel mappings. */
+    for ( i = 0; i < NR_IRQS; i++ )
+        irq_to_evtchn[i] = -1;
 
     for ( i = 0; i < NR_DYNIRQS; i++ )
     {
-        dynirq_to_evtchn[i] = -1;
-        dynirq_bindcount[i] = 0;
-    }
+        /* Dynamic IRQ space is currently unbound. Zero the refcnts. */
+        irq_bindcount[dynirq_to_irq(i)] = 0;
 
-    spin_lock_init(&dynirq_lock);
+        irq_desc[dynirq_to_irq(i)].status  = IRQ_DISABLED;
+        irq_desc[dynirq_to_irq(i)].action  = 0;
+        irq_desc[dynirq_to_irq(i)].depth   = 1;
+        irq_desc[dynirq_to_irq(i)].handler = &dynirq_type;
+    }
 
-    for ( i = 0; i < NR_DYNIRQS; i++ )
+    for ( i = 0; i < NR_PIRQS; i++ )
     {
-        irq_desc[i + DYNIRQ_BASE].status  = IRQ_DISABLED;
-        irq_desc[i + DYNIRQ_BASE].action  = 0;
-        irq_desc[i + DYNIRQ_BASE].depth   = 1;
-        irq_desc[i + DYNIRQ_BASE].handler = &dynirq_type;
+        /* Phys IRQ space is statically bound (1:1 mapping). Nail refcnts. */
+        irq_bindcount[pirq_to_irq(i)] = 1;
+
+        irq_desc[pirq_to_irq(i)].status  = IRQ_DISABLED;
+        irq_desc[pirq_to_irq(i)].action  = 0;
+        irq_desc[pirq_to_irq(i)].depth   = 1;
+        irq_desc[pirq_to_irq(i)].handler = &pirq_type;
     }
 
     (void)setup_irq(bind_virq_to_irq(VIRQ_ERROR), &error_action);
-    
-#ifdef CONFIG_PCI
-    /* Also initialise the physical IRQ handlers. */
-    physirq_init();
-#endif
 }
diff --git a/xenolinux-2.4.25-sparse/arch/xen/kernel/physirq.c b/xenolinux-2.4.25-sparse/arch/xen/kernel/physirq.c
deleted file mode 100644 (file)
index 7c04c9d..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-/* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
- ****************************************************************************
- * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge
- ****************************************************************************
- *
- *        File: physirq.c
- *      Author: Rolf Neugebauer (rolf.neugebauer@intel.com)
- *        Date: Mar 2004
- * 
- * Description: guests may receive virtual interrupts directly 
- *              corresponding to physical interrupts. these virtual
- *              interrupts require special handling provided 
- *              by the virq irq type.
- */
-
-#ifdef CONFIG_PCI
-
-#include <linux/config.h>
-#include <asm/atomic.h>
-#include <asm/irq.h>
-#include <asm/hypervisor.h>
-#include <asm/system.h>
-
-#include <linux/irq.h>
-#include <linux/sched.h>
-
-#include <asm/hypervisor-ifs/hypervisor-if.h>
-#include <asm/hypervisor-ifs/physdev.h>
-
-static void physirq_interrupt(int irq, void *unused, struct pt_regs *ptregs);
-
-static int setup_event_handler = 0;
-
-static unsigned int startup_physirq_event(unsigned int irq)
-{
-    physdev_op_t op;
-    int err;
-
-    printk("startup_physirq_event %d\n", irq);
-
-    /*
-     * install a interrupt handler for physirq event when called first time
-     * we actually are never executing the handler as _EVENT_PHYSIRQ is 
-     * handled specially in hypervisor.c But we need to enable the event etc.
-     */
-    if ( !setup_event_handler )
-    {
-        printk("startup_physirq_event %d: setup event handler\n", irq);
-        /* set up a event handler to demux virtualised physical interrupts */
-        err = request_irq(IRQ_FROM_XEN_VIRQ(VIRQ_PHYSIRQ), physirq_interrupt, 
-                          SA_SAMPLE_RANDOM, "physirq", NULL);
-        if ( err )
-        {
-            printk(KERN_WARNING "Could not allocate physirq interrupt\n");
-            return err;
-        }
-        setup_event_handler = 1;
-    }
-
-    /*
-     * request the irq from hypervisor
-     */
-    op.cmd = PHYSDEVOP_REQUEST_IRQ;
-    op.u.request_irq.irq   = irq;
-    if ( (err = HYPERVISOR_physdev_op(&op)) != 0 )
-    {
-        printk(KERN_ALERT "could not get IRQ %d from Xen\n", irq);
-        return err;
-    }
-    return 0;
-}
-/*
- * This is a dummy interrupt handler.
- * It should never be called. events for physical interrupts are handled
- * differently in hypervisor.c
- */
-static void physirq_interrupt(int irq, void *unused, struct pt_regs *ptregs)
-{
-    printk("XXX This should never be called!");
-}
-
-
-/*
- * IRQ is not needed anymore.
- */
-static void shutdown_physirq_event(unsigned int irq)
-{
-    physdev_op_t op;
-    int err;
-
-    printk("shutdown_phys_irq called.");
-
-    /*
-     * tell hypervisor
-     */
-    op.cmd = PHYSDEVOP_FREE_IRQ;
-    op.u.free_irq.irq   = irq;
-    if ( (err = HYPERVISOR_physdev_op(&op)) != 0 )
-    {
-        printk(KERN_ALERT "could not free IRQ %d\n", irq);
-        return;
-    }
-    return;
-}
-
-
-static void enable_physirq_event(unsigned int irq)
-{
-    /* XXX just enable all phys interrupts for now */
-    enable_irq(IRQ_FROM_XEN_VIRQ(VIRQ_PHYSIRQ));
-}
-
-static void disable_physirq_event(unsigned int irq)
-{
-    /* XXX just disable all phys interrupts for now */
-    disable_irq(IRQ_FROM_XEN_VIRQ(VIRQ_PHYSIRQ));
-}
-
-static void ack_physirq_event(unsigned int irq)
-{
-    /* clear bit */
-    if ( irq <= 0 || irq >= 32 )
-    {
-        printk("wrong irq %d\n", irq);
-    }
-
-    clear_bit(irq, &HYPERVISOR_shared_info->physirq_pend);
-}
-
-static void end_physirq_event(unsigned int irq)
-{
-    int err;
-    physdev_op_t op;
-
-    /* call hypervisor */
-    op.cmd = PHYSDEVOP_FINISHED_IRQ;
-    op.u.finished_irq.irq   = irq;
-    if ( (err = HYPERVISOR_physdev_op(&op)) != 0 )
-    {
-        printk(KERN_ALERT "could not finish IRQ %d\n", irq);
-        return;
-    }
-    return;
-}
-
-static struct hw_interrupt_type physirq_irq_type = {
-    "physical-irq",
-    startup_physirq_event,
-    shutdown_physirq_event,
-    enable_physirq_event,
-    disable_physirq_event,
-    ack_physirq_event,
-    end_physirq_event,
-    NULL
-};
-
-
-
-void __init physirq_init(void)
-{
-    int i;
-
-    printk("Initialise irq handlers [%d-%d] for physical interrupts.\n",
-           PHYS_IRQ_BASE, PHYS_IRQ_BASE+NR_PHYS_IRQS-1);
-
-    for ( i = 0; i < NR_PHYS_IRQS; i++ )
-    {
-        irq_desc[i + PHYS_IRQ_BASE].status  = IRQ_DISABLED;
-        irq_desc[i + PHYS_IRQ_BASE].action  = 0;
-        irq_desc[i + PHYS_IRQ_BASE].depth   = 1;
-        irq_desc[i + PHYS_IRQ_BASE].handler = &physirq_irq_type;
-    }
-}
-
-#endif
index 6d175ce6abc7f1186dcfccab832b2e828c911545..a05b99640eccb8a6ca392c471dc1a766d4d0022e 100644 (file)
 
 #define NR_IRQS   (NR_PIRQS + NR_DYNIRQS)
 
-extern void physirq_init(void);
+#define pirq_to_irq(_x)   ((_x) + PIRQ_BASE)
+#define irq_to_pirq(_x)   ((_x) - PIRQ_BASE)
+
+#define dynirq_to_irq(_x) ((_x) + DYNIRQ_BASE)
+#define irq_to_dynirq(_x) ((_x) - DYNIRQ_BASE)
 
 /* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */
 extern int  bind_virq_to_irq(int virq);
@@ -40,14 +44,13 @@ extern void unbind_virq_from_irq(int virq);
 extern int  bind_evtchn_to_irq(int evtchn);
 extern void unbind_evtchn_from_irq(int evtchn);
 
-#define irq_cannonicalize(_irq) (_irq)
+static __inline__ int irq_cannonicalize(int irq)
+{
+    return (irq == 2) ? 9 : irq;
+}
 
 extern void disable_irq(unsigned int);
 extern void disable_irq_nosync(unsigned int);
 extern void enable_irq(unsigned int);
 
-#ifdef CONFIG_X86_LOCAL_APIC
-#define ARCH_HAS_NMI_WATCHDOG          /* See include/linux/nmi.h */
-#endif
-
 #endif /* _ASM_IRQ_H */